package src.ee.ioc.smaug.world.evolution;

import java.util.Random;

/**
 * Different types of the crossover
 * @author Margarita Spichakova
 *
 */
public class Crossover {
    /**
     * Child 1
     */
    static boolean[] child1;

    /**
     * Child 2
     */
    static boolean[] child2;

    /**
     * Apply crossover according to parameter
     * @param parent1 one individual represented as sequence of boolean values
     * @param parent2 second individual represented as sequence of boolean values
     */
    public static void apply(boolean[] parent1, boolean[] parent2) {
        child1 = new boolean[parent1.length];
        child2 = new boolean[parent1.length];

        switch (EnvDescription.CROSStype) {
        case ONE_POINT_CROSSOVER:
            onePointCrossover(parent1, parent2);
            break;
        case TWO_POINT_CROSSOVER:
            twoPointCrossover(parent1, parent2);
            break;
        }
    }

    /**
     * Changes parents to children. Two parts of the chromosomes are swaped.
     * One random point.
     * Standart version without saving structure
     * @param parent1 one individual represented as sequence of boolean values
     * @param parent2 second individual represented as sequence of boolean values
     */
    private static void onePointCrossover(boolean[] parent1, boolean[] parent2) {
        Random rnd = new Random();
        child1 = new boolean[parent1.length];
        child2 = new boolean[parent1.length];
        int crossoverPoint = rnd.nextInt(parent1.length - 1) + 1;
        for (int i = 0; i < crossoverPoint; i++) {
            child1[i] = parent1[i];
            child2[i] = parent2[i];
        }

        for (int i = crossoverPoint; i < parent1.length; i++) {
            child1[i] = parent2[i];
            child2[i] = parent1[i];
        }

    }

    /**
     * Changes parents to children. Three parts of the chromosomes are swaped
     * Two random points.
     * Standart version without saving structure
     * @param parent1 parent1 one individual represented as sequence of boolean values
     * @param parent2 second individual represented as sequence of boolean values
     */
    private static void twoPointCrossover(boolean[] parent1, boolean[] parent2) {
        Random rnd = new Random();
        child1 = new boolean[parent1.length];
        child2 = new boolean[parent1.length];
        int crossoverPoint1 = rnd.nextInt(parent1.length - 1) + 1;
        int crossoverPoint2 = rnd.nextInt(parent1.length - 1) + 1;

        if (crossoverPoint1 > crossoverPoint2) {

            int buff = crossoverPoint2;
            crossoverPoint2 = crossoverPoint1;
            crossoverPoint1 = buff;

        }

        for (int i = 0; i < crossoverPoint1; i++) {
            child1[i] = parent1[i];
            child2[i] = parent2[i];
        }

        for (int i = crossoverPoint1; i < crossoverPoint2; i++) {
            child2[i] = parent1[i];
            child1[i] = parent2[i];
        }

        for (int i = crossoverPoint2; i < parent1.length; i++) {
            child1[i] = parent1[i];
            child2[i] = parent2[i];
        }

    }

}
